/* main.c -- MQTT client example
 *
 * Copyright (c) 2014-2015, Tuan PM <tuanpm at live dot com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * * Neither the name of Redis nor the names of its contributors may be used
 * to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#include "ets_sys.h"
#include "driver/uart.h"
#include "osapi.h"
#include "mqtt.h"
#include "wifi.h"
#include "config.h"
#include "debug.h"
#include "gpio.h"
#include "user_interface.h"
#include "mem.h"

/******************************************************************************
 * FunctionName : user_rf_cal_sector_set
 * Description  : SDK just reversed 4 sectors, used for rf init data and paramters.
 *                We add this function to force users to set rf cal sector, since
 *                we don't know which sector is free in user's application.
 *                sector map for last several sectors : ABCCC
 *                A : rf cal
 *                B : rf init data
 *                C : sdk parameters
 * Parameters   : none
 * Returns      : rf cal sector
 *******************************************************************************/	
#define CS 12
#define DIN 13
#define CLK 14

MQTT_Client mqttClient;
typedef unsigned long u32_t;
static ETSTimer sntp_timer;
static os_timer_t os_timer;

static uint8_t disp[][8]={
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //   32 0
{0x0,0x10,0x10,0x10,0x10,0x10,0x0,0x10},   // ! 33 1
{0x0,0x6,0x6,0x0,0x0,0x0,0x0,0x0},         // " 34 2
{0x0,0x0,0x14,0x3E,0x14,0x3E,0x14,0x0},    // # 35 3
{0x0,0x8,0x3E,0x28,0x3E,0xA,0x3E,0x8},     // $ 36 4
{0x0,0x62,0x64,0x8,0x10,0x26,0x46,0x0},    // % 37 5
{0x20,0x50,0x88,0x54,0x22,0x54,0x28,0x14}, // & 38 6
{0x0,0x0,0x10,0x10,0x0,0x0,0x0,0x0,},      // ' 39 7
{0x0,0x0,0x10,0x20,0x20,0x20,0x10,0x0},    // ( 40 8
{0x0,0x0,0x10,0x8,0x8,0x8,0x10,0x0},       // ) 41 9
{0x0,0x0,0x2A,0x1C,0x1C,0x2A,0x0,0x0},     // * 42 10
{0x0,0x0,0x8,0x8,0x3E,0x8,0x8,0x0},        // + 43 11
{0x0,0x0,0x0,0x0,0x18,0x18,0x8,0x10},      // , 44 12
{0x0,0x0,0x0,0x0,0x3E,0x0,0x0,0x0},        // - 45 13
{0x0,0x0,0x0,0x0,0x0,0x18,0x18,0x0},       // . 46 14
{0x0,0x0,0x2,0x4,0x8,0x10,0x20,0x0},       // / 47 15
{0x3C,0x42,0x42,0x42,0x42,0x42,0x42,0x3C}, // 0 48 16
{0x0,0x8,0x18,0x8,0x8,0x8,0x8,0x8},        // 1 49 17
{0x0,0x18,0x24,0x4,0x8,0x10,0x20,0x3C},    // 2 50 18
{0x0,0x18,0x24,0x4,0x8,0x4,0x24,0x18},     // 3 51 19
{0x0,0x0,0x8,0x18,0x28,0x7C,0x8,0x8},      // 4 52 20
{0x0,0x3C,0x20,0x3C,0x4,0x4,0x3C,0x0},     // 5 53 21
{0x3C,0x20,0x20,0x3C,0x24,0x24,0x3C,0x0},  // 6 54 22
{0x3E,0x22,0x4,0x8,0x8,0x8,0x8,0x8},       // 7 55 23
{0x0,0x3E,0x22,0x22,0x3E,0x22,0x22,0x3E},  // 8 56 24
{0x3E,0x22,0x22,0x3E,0x2,0x2,0x2,0x3E},    // 9 57 25
{0x0,0x0,0x10,0x10,0x0,0x10,0x10,0x0},     // : 58 26
{0x0,0x0,0x10,0x10,0x0,0x10,0x20,0x0},     // ; 59 27
{0x0,0x0,0x8,0x10,0x20,0x10,0x8,0x0},      // < 60 28
{0x0,0x0,0x0,0x7C,0x0,0x7C,0x0,0x0,},      // = 61 29
{0x0,0x0,0x10,0x8,0x4,0x8,0x10,0x0},       // > 62 30
{0x0,0x10,0x28,0x8,0x10,0x10,0x0,0x10},    // ? 63 31
{0x0,0x7C,0x82,0xBA,0xAA,0xBA,0x84,0x70},  // @ 64 32
{0x8,0x14,0x22,0x3E,0x22,0x22,0x22,0x22},  // A 65 33
{0x3C,0x22,0x22,0x3E,0x22,0x22,0x3C,0x0},  // B 66 34
{0x3C,0x40,0x40,0x40,0x40,0x40,0x3C,0x0},  // C 67 35
{0x7C,0x42,0x42,0x42,0x42,0x42,0x7C,0x0},  // D 68 36
{0x7C,0x40,0x40,0x7C,0x40,0x40,0x40,0x7C}, // E 69 37
{0x7C,0x40,0x40,0x7C,0x40,0x40,0x40,0x40}, // F 70 38
{0x3C,0x40,0x40,0x40,0x40,0x44,0x44,0x3C}, // G 71 39
{0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44}, // H 72 40
{0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x7C}, // I 73 41
{0x3C,0x8,0x8,0x8,0x8,0x8,0x48,0x30},      // J 74 42
{0x0,0x24,0x28,0x30,0x20,0x30,0x28,0x24},  // K 75 43
{0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C}, // L 76 44
{0x81,0xC3,0xA5,0x99,0x81,0x81,0x81,0x81}, // M 77 45
{0x0,0x42,0x62,0x52,0x4A,0x46,0x42,0x0},   // N 78 46
{0x3C,0x42,0x42,0x42,0x42,0x42,0x42,0x3C}, // O 79 47
{0x3C,0x22,0x22,0x22,0x3C,0x20,0x20,0x20}, // P 80 48
{0x1C,0x22,0x22,0x22,0x22,0x26,0x22,0x1D}, // Q 81 49
{0x3C,0x22,0x22,0x22,0x3C,0x24,0x22,0x21}, // R 82 50
{0x0,0x1E,0x20,0x20,0x3E,0x2,0x2,0x3C},    // S 83 51
{0x0,0x3E,0x8,0x8,0x8,0x8,0x8,0x80},       // T 84 52
{0x42,0x42,0x42,0x42,0x42,0x42,0x22,0x1C}, // U 85 53
{0x42,0x42,0x42,0x42,0x42,0x42,0x24,0x18}, // V 86 54
{0x0,0x49,0x49,0x49,0x49,0x2A,0x1C,0x0},   // W 87 55
{0x0,0x41,0x22,0x14,0x8,0x14,0x22,0x41},   // X 88 56
{0x41,0x22,0x14,0x8,0x8,0x8,0x8,0x8},      // Y 89 57
{0x0,0x7F,0x2,0x4,0x8,0x10,0x20,0x7F},     // Z 90 58
{0x0,0x30,0x20,0x20,0x20,0x20,0x30,0x0},   // [ 91 59
{0x0,0x0,0x40,0x20,0x10,0x8,0x4,0x0},      // \ 92 60
{0x0,0x18,0x8,0x8,0x8,0x8,0x18,0x0},       // ] 93 61
{0x0,0x10,0x28,0x44,0x0,0x0,0x0,0x0},      // ^ 94 62
{0x0,0x0,0x0,0x0,0x0,0x0,0x7E,0x0},        // _ 95 63
{0x0,0x10,0x8,0x0,0x0,0x0,0x0,0x0},        // ` 96 64
{0x0,0x0,0x18,0x4,0x1C,0x24,0x1E,0x0},     // a 97 65
{0x0,0x10,0x10,0x10,0x18,0x14,0x18,0x0},   // b 98 66
{0x0,0x0,0x0,0x18,0x20,0x20,0x18,0x0},     // c 99 67
{0x0,0x8,0x8,0x18,0x28,0x28,0x18,0x0},     // d 100 68
{0x0,0x0,0x18,0x24,0x3C,0x20,0x1C,0x0},    // e 101 69
{0x0,0x0,0x1C,0x20,0x3C,0x20,0x20,0x0},    // f 102 70
{0x0,0x0,0x18,0x24,0x1C,0x4,0x3C,0x0},     // g 103 71
{0x0,0x0,0x20,0x20,0x30,0x28,0x28,0x0},    // h 104 72
{0x0,0x0,0x10,0x0,0x10,0x10,0x10,0x0},     // i 105 73
{0x0,0x0,0x10,0x0,0x10,0x50,0x30,0x0},     // j 106 74
{0x0,0x0,0x24,0x28,0x30,0x28,0x24,0x0},    // k 107 75
{0x0,0x0,0x10,0x10,0x10,0x10,0x10,0x0},   // l 108 76
{0x0,0x0,0x0,0x38,0x54,0x54,0x54,0x0},     // m 109 77
{0x0,0x0,0x0,0x8,0x14,0x14,0x14,0x0},      // n 110 78
{0x0,0x0,0x0,0x8,0x14,0x14,0x8,0x0},       // o 111 79
{0x0,0x0,0x30,0x28,0x30,0x20,0x20,0x0},    // p 112 80
{0x0,0x0,0x18,0x28,0x18,0x8,0x8,0x0},      // q 113 81
{0x0,0x0,0x0,0x28,0x30,0x20,0x20,0x0},     // r 114 82
{0x0,0x0,0x38,0x20,0x38,0x8,0x38,0x0},     // s 115 83
{0x0,0x0,0x0,0x10,0x38,0x10,0x18,0x0},     // t 116 84
{0x0,0x0,0x0,0x28,0x28,0x28,0x38,0x0},     // u 117 85
{0x0,0x0,0x0,0x28,0x28,0x28,0x10,0x0,},    // v 118 86
{0x0,0x0,0x0,0x54,0x54,0x54,0x28,0x0},     // w 119 87
{0x0,0x0,0x0,0x28,0x10,0x28,0x0,0x0,},     // x 120 88
{0x0,0x0,0x28,0x28,0x38,0x8,0x8,0x0},      // y 121 89
{0x0,0x0,0x0,0x3C,0x8,0x10,0x3C,0x0},      // z 122 90
{0x0,0x10,0x20,0x20,0x40,0x20,0x20,0x10},  // { 123 91
{0x0,0x10,0x10,0x10,0x10,0x10,0x10,0x0},  // | 124 92
{0x0,0x10,0x8,0x8,0x4,0x8,0x8,0x10},      // } 125 93
{0x0,0x0,0x0,0x24,0x54,0x48,0x0,0x0},     // ~ 126 94
};

void delay_ms(uint32 x)
{
	for(x=0;x>0;x--)
	{
	  os_delay_us(1000);
	}
}

void Write_Max7219_byte(uint8_t DATA)         
{
  uint8_t i; 
	GPIO_OUTPUT_SET(GPIO_ID_PIN(CS), 0);  
  for(i=8;i>=1;i--)
  {		  
		GPIO_OUTPUT_SET(GPIO_ID_PIN(CLK), 0);
		if(DATA&0x80){
			GPIO_OUTPUT_SET(GPIO_ID_PIN(DIN), 1);	
		}
		else{
			GPIO_OUTPUT_SET(GPIO_ID_PIN(DIN), 0);
		} 
    DATA=DATA<<1;
		GPIO_OUTPUT_SET(GPIO_ID_PIN(CLK), 1);
  }   
}
void Write_Max7219_1(uint8_t add1,uint8_t dat1)
{ 
	GPIO_OUTPUT_SET(GPIO_ID_PIN(CS), 0);  
	Write_Max7219_byte(add1);           
	Write_Max7219_byte(dat1);
	GPIO_OUTPUT_SET(GPIO_ID_PIN(CS), 1);                                      
}

void Write_Max7219_2(uint8_t add2,uint8_t dat2)
{
	GPIO_OUTPUT_SET(GPIO_ID_PIN(CS), 0); 
	Write_Max7219_byte(add2);
	Write_Max7219_byte(dat2);
	GPIO_OUTPUT_SET(GPIO_ID_PIN(CLK), 1);
	Write_Max7219_byte(0x00);  
	Write_Max7219_byte(0x00);
	GPIO_OUTPUT_SET(GPIO_ID_PIN(CS), 1); 
}

void Write_Max7219_3(uint8_t add3,uint8_t dat3)
{
	GPIO_OUTPUT_SET(GPIO_ID_PIN(CS), 0); 
	Write_Max7219_byte(add3);
	Write_Max7219_byte(dat3);
	GPIO_OUTPUT_SET(GPIO_ID_PIN(CLK), 1);
	Write_Max7219_byte(0x00); 
	Write_Max7219_byte(0x00);
	Write_Max7219_byte(0x00);
	Write_Max7219_byte(0x00);
	GPIO_OUTPUT_SET(GPIO_ID_PIN(CS), 1);
}

void Write_Max7219_4(uint8_t add4,uint8_t dat4)
{
	GPIO_OUTPUT_SET(GPIO_ID_PIN(CS), 0); 
	Write_Max7219_byte(add4);
	Write_Max7219_byte(dat4);
	GPIO_OUTPUT_SET(GPIO_ID_PIN(CLK), 1);
	Write_Max7219_byte(0x00); 
	Write_Max7219_byte(0x00);
	Write_Max7219_byte(0x00);
	Write_Max7219_byte(0x00);
  Write_Max7219_byte(0x00);
  Write_Max7219_byte(0x00);
	GPIO_OUTPUT_SET(GPIO_ID_PIN(CS), 1);
}

void Init_MAX7219(void)
{
	PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12);//cs
	PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13);//din
	PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, FUNC_GPIO14);//clk
	GPIO_OUTPUT_SET(GPIO_ID_PIN(CS), 1); 
	GPIO_OUTPUT_SET(GPIO_ID_PIN(DIN), 1); 
	GPIO_OUTPUT_SET(GPIO_ID_PIN(CLK), 1); 

 Write_Max7219_1(0x09, 0x00);      
 Write_Max7219_1(0x0a, 0x03);      
 Write_Max7219_1(0x0b, 0x07);       
 Write_Max7219_1(0x0c, 0x01);     
 Write_Max7219_1(0x0f, 0x00);      
 
 Write_Max7219_2(0x09, 0x00);       
 Write_Max7219_2(0x0a, 0x03);       
 Write_Max7219_2(0x0b, 0x07);       
 Write_Max7219_2(0x0c, 0x01);      
 Write_Max7219_2(0x0f, 0x00);      
 
 Write_Max7219_3(0x09, 0x00);     
 Write_Max7219_3(0x0a, 0x03);     
 Write_Max7219_3(0x0b, 0x07);       
 Write_Max7219_3(0x0c, 0x01);       
 Write_Max7219_3(0x0f, 0x00);      
  
 Write_Max7219_4(0x09, 0x00);      
 Write_Max7219_4(0x0a, 0x03);      
 Write_Max7219_4(0x0b, 0x07);       
 Write_Max7219_4(0x0c, 0x01);      
 Write_Max7219_4(0x0f, 0x00);       
}

void roll_4(char LEDstring[],uint32_t time)
{
  uint8_t length = strlen(LEDstring);
  uint8_t line=0;
	uint8_t i=0;
	uint8_t num=1;
  for(i=0; i<length; i++){
   for(num=1;  num<5; num++){
    switch(num){
       case 1:
         if(i >= 0){
           for(line=1;line<9;line++)
           Write_Max7219_1(line,disp[LEDstring[i] - 32][line-1]); 
         }   
       break;
       case 2:
         if((i-1) >= 0){
           for(line=1;line<9;line++)
            Write_Max7219_2(line,disp[LEDstring[i-1] - 32][line-1]);
         }
         else{
          for(line=1;line<9;line++)
            Write_Max7219_2(line,disp[0][line-1]);
         }
       break;
       case 3:
         if((i-2) >= 0){
           for(line=1;line<9;line++)
             Write_Max7219_3(line,disp[LEDstring[i-2] - 32][line-1]);
         }
         else{
          for(line=1;line<9;line++)
            Write_Max7219_3(line,disp[0][line-1]);
         }  
       break;
       case 4:
        if((i-3) >= 0){
           for(line=1;line<9;line++)
             Write_Max7219_4(line,disp[LEDstring[i-3] - 32][line-1]);
         }
         else{
          for(line=1;line<9;line++)
            Write_Max7219_4(line,disp[0][line-1]);
         }  
       break;
       default:
         break;
    }
  }
  os_delay_us(time);
	os_delay_us(time);
	os_delay_us(time);
 }
}

void sntpfn() {
	u32_t ts = 0;
	ts = sntp_get_current_timestamp();
	os_printf("current time : %s\n", sntp_get_real_time(ts));
	if (ts == 0) {
		//os_printf("did not get a valid time from sntp server\n");
	} else {
		os_timer_disarm(&sntp_timer);
		MQTT_Connect(&mqttClient);
	}
}

void wifiConnectCb(uint8_t status) {
	if (status == STATION_GOT_IP) {
		sntp_setservername(0, "pool.ntp.org"); // set sntp server after got ip address
		sntp_init();
		os_timer_disarm(&sntp_timer);
		os_timer_setfn(&sntp_timer, (os_timer_func_t *) sntpfn, NULL);
		os_timer_arm(&sntp_timer, 1000, 1);        //1s
	} else {
		MQTT_Disconnect(&mqttClient);
	}
}

void mqttConnectedCb(uint32_t *args) {
	MQTT_Client* client = (MQTT_Client*) args;
	MQTT_Subscribe(client, "/LED/in", 0);//订阅主题
}

void mqttDisconnectedCb(uint32_t *args) {
	MQTT_Client* client = (MQTT_Client*) args;
	INFO("MQTT: Disconnected\r\n");
}

void mqttPublishedCb(uint32_t *args) {
	MQTT_Client* client = (MQTT_Client*) args;
	INFO("MQTT: Published\r\n");
}
uint8_t pov_date[] ="HELLO LED";
void mqttDataCb(uint32_t *args, const char* topic, uint32_t topic_len,
		uint8_t *data, uint32_t data_len) {

	MQTT_Client* client = (MQTT_Client*) args;

	// // 如果接收到指令是1，GPIO15输出为低,也就是LED开灯，同时发布消息，主题是/LED/out，信息是LED open
	// if (data[0] == '1') {
	// 	MQTT_Publish(client, "/LED/out", "LED open",
	// 			strlen("LED open"), 0, 0);
	// }

	// //如果接收到指令是0，GPIO15为高,也就是LED关灯，同时发布消息，主题是/LED/out，信息是LED off
	// if (data[0] == '0') {
	// 	MQTT_Publish(client, "/LED/out", "LED off",
	// 			strlen("LED off"), 0, 0);
	// }
  
  strcpy(pov_date,data);
	MQTT_Publish(client, "/LED/out", "pov run",
				strlen("pov run"), 0, 0);
	memset(data,0,100);   
}

uint32 ICACHE_FLASH_ATTR
user_rf_cal_sector_set(void) {
	enum flash_size_map size_map = system_get_flash_size_map();
	uint32 rf_cal_sec = 0;

	switch (size_map) {
	case FLASH_SIZE_4M_MAP_256_256:
		rf_cal_sec = 128 - 5;
		break;

	case FLASH_SIZE_8M_MAP_512_512:
		rf_cal_sec = 256 - 5;
		break;

	case FLASH_SIZE_16M_MAP_512_512:
	case FLASH_SIZE_16M_MAP_1024_1024:
		rf_cal_sec = 512 - 5;
		break;

	case FLASH_SIZE_32M_MAP_512_512:
	case FLASH_SIZE_32M_MAP_1024_1024:
		rf_cal_sec = 1024 - 5;
		break;

	default:
		rf_cal_sec = 0;
		break;
	}

	return rf_cal_sec;
}

void POV_Task_Run(void){
   roll_4(pov_date,50500);
}

void user_init(void) {

	uart_init(BIT_RATE_115200, BIT_RATE_115200);

	CFG_Load();

  Init_MAX7219();

	MQTT_InitConnection(&mqttClient, sysCfg.mqtt_host, sysCfg.mqtt_port,
			sysCfg.security);
	//MQTT_InitConnection(&mqttClient, "192.168.11.122", 1880, 0);
	MQTT_InitClient(&mqttClient, sysCfg.device_id, sysCfg.mqtt_user,
			sysCfg.mqtt_pass, sysCfg.mqtt_keepalive, 1);
	//MQTT_InitClient(&mqttClient, "client_id", "user", "pass", 120, 1);
	MQTT_InitLWT(&mqttClient, "/lwt", "offline", 0, 0);
	MQTT_OnConnected(&mqttClient, mqttConnectedCb);
	MQTT_OnDisconnected(&mqttClient, mqttDisconnectedCb);
	MQTT_OnPublished(&mqttClient, mqttPublishedCb);
	MQTT_OnData(&mqttClient, mqttDataCb);
	WIFI_Connect(sysCfg.sta_ssid, sysCfg.sta_pwd, wifiConnectCb);
	/** 关闭该定时器 */
  os_timer_disarm( &os_timer );
	/** 配置该定时器回调函数 */
	os_timer_setfn( &os_timer, (ETSTimerFunc *) ( POV_Task_Run ), NULL );
	/** 启动该定时器 */
	os_timer_arm( &os_timer, 5000, true );

	INFO("\r\nSystem started ...\r\n");

}
